using System;
using System.Collections.Generic;
using System.Text;

using System.Collections;
using System.Diagnostics;
using System.Xml;

using System.Reflection;
using System.Reflection.Emit;


using BILab.Technical.BI.ETL.Pipeline.Common;

using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;

using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[assembly: CLSCompliant(false)]
namespace BILab.Technical.BI.ETL.Pipeline.XmlDestination
{
	[DtsPipelineComponent(
		ComponentType=ComponentType.DestinationAdapter,
		DisplayName="XML Destination Adapter",
	   UITypeName = "BILab.Technical.BI.ETL.Pipeline.XmlDestination.XmlDestinationAdapterUI,XmlDestination,Version=1.0.0.0,Culture=neutral,PublicKeyToken=e4e8dcd3244436f2"
		)
	]
	public class XmlDestinationAdapter: PipelineComponent
	{
		#region Contants, Members and Properties

		private const string Const_FileName_AttributeName = "Filename";
		private const string Const_XmlRootTag_AttributeName = "Xml Root Tag";
		private const string Const_XmlRowTag_AttributeName = "Xml Row Tag";
		private const string Const_XmlNbOfRowsTag_AttributeName = "Xml Number of Rows Tag";
		private const string Const_OutputNbOfRows_AttributeName = "Output Number Of Rows";
		

		private ColumnInformation[] colInfos;

		private int _lineCounter;
		private string _fileName;
		private XmlWriter _xml;
		private string _Xml_RootTag;
		private string _Xml_NbOfRowsTag;
		private string _Xml_RowTag;
		private bool _doOutputNumberOfRows;

		public bool DoOutputNumberOfRows
		{
			get { return _doOutputNumberOfRows; }
			set { _doOutputNumberOfRows = value; }
		}


		private string Xml_RowTag
		{
			get { return _Xml_RowTag; }
			set { _Xml_RowTag = value; }
		}

		private string Xml_NbOfRowsTag
		{
			get { return _Xml_NbOfRowsTag; }
			set { _Xml_NbOfRowsTag = value; }
		}

		private string Xml_RootTag
		{
			get { return _Xml_RootTag; }
			set { _Xml_RootTag = value; }
		}


		private XmlWriter Xml
		{
			get { return _xml; }
			set { _xml = value; }
		}

		private string FileName
		{
			get { return _fileName; }
			set { _fileName = value; }
		}

		private int LineCounter
		{
			get { return _lineCounter; }
			set { _lineCounter = value; }
		}
		#endregion

		public override void ProvideComponentProperties()
		{
			base.ProvideComponentProperties();
			// Add properties and set the default value;
			base.ComponentMetaData.OutputCollection.RemoveAll();

			// - filename
			IDTSCustomProperty90 filenameProperty = base.ComponentMetaData.CustomPropertyCollection.New();
			filenameProperty.Name = Const_FileName_AttributeName;
			filenameProperty.State = DTSPersistState.PS_PERSISTASCDATA;
			filenameProperty.UITypeEditor = "System.Windows.Forms.Design.FileNameEditor, System.Design, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
			filenameProperty.Value = "";

			// - Xml Root Tag
			IDTSCustomProperty90 xmlRootProperty = base.ComponentMetaData.CustomPropertyCollection.New();
			xmlRootProperty.Name = Const_XmlRootTag_AttributeName;
			xmlRootProperty.State = DTSPersistState.PS_PERSISTASCDATA;
			xmlRootProperty.Value = "XmlDestination";

			// - Xml Row Tag
			IDTSCustomProperty90 xmlRowProperty = base.ComponentMetaData.CustomPropertyCollection.New();
			xmlRowProperty.Name = Const_XmlRowTag_AttributeName;
			xmlRowProperty.State = DTSPersistState.PS_PERSISTASCDATA;
			xmlRowProperty.Value = "DataRow";

			// - Do we output number of rows into the Xml file
			IDTSCustomProperty90 xmlDoOutputNbOfRows = base.ComponentMetaData.CustomPropertyCollection.New();
			xmlDoOutputNbOfRows.Name = Const_OutputNbOfRows_AttributeName;
			xmlDoOutputNbOfRows.State = DTSPersistState.PS_PERSISTASCDATA;
			xmlDoOutputNbOfRows.Value = true;

			// - Xml Nummber of Row Tag
			IDTSCustomProperty90 xmlNbRowProperty = base.ComponentMetaData.CustomPropertyCollection.New();
			xmlNbRowProperty.Name = Const_XmlNbOfRowsTag_AttributeName;
			xmlNbRowProperty.State = DTSPersistState.PS_PERSISTASCDATA;
			xmlNbRowProperty.Value = "NumberOfRows";
		}

		public override DTSValidationStatus Validate()
		{
			bool cancel = false;

			this.FileName = this.ComponentMetaData.CustomPropertyCollection[Const_FileName_AttributeName].Value.ToString(); ;
			this.Xml_RootTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlRootTag_AttributeName].Value;
			this.Xml_RowTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlRowTag_AttributeName].Value;
			this.DoOutputNumberOfRows = (bool)this.ComponentMetaData.CustomPropertyCollection[Const_OutputNbOfRows_AttributeName].Value;
			this.Xml_NbOfRowsTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlNbOfRowsTag_AttributeName].Value;
			

			DTSValidationStatus status =  base.Validate();
			if( status == DTSValidationStatus.VS_ISVALID)
			{
				if (this.FileName.Length == 0)
				{
					this.ComponentMetaData.FireError(0,ComponentMetaData.Name,Resource.FilenameNotSet,string.Empty,0,out cancel);
					return DTSValidationStatus.VS_ISBROKEN;
				}

				if (this.Xml_RootTag.Length == 0)
				{
					this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlRootTagNotSet, string.Empty, 0, out cancel);
					return DTSValidationStatus.VS_ISBROKEN;
				}

				if (this.Xml_RowTag.Length == 0)
				{
					this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlRowTagNotSet, string.Empty, 0, out cancel);
					return DTSValidationStatus.VS_ISBROKEN;
				}

				if (this.Xml_NbOfRowsTag.Length == 0)
				{
					this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlNbRowsTagNotSet, string.Empty, 0, out cancel);
					return DTSValidationStatus.VS_ISBROKEN;
				}


			}
			return DTSValidationStatus.VS_ISVALID;
		}

		public override void PreExecute()
		{
			// STEP 1=
			// Destination file management

			/* 1.1: gets the filename, test if the file exist (and delete it )*/
			this.FileName = this.ComponentMetaData.CustomPropertyCollection[Const_FileName_AttributeName].Value.ToString();
			if (System.IO.File.Exists(this.FileName))
			{
				System.IO.File.Delete(this.FileName);
			}

			/*1.2: Creates the XmlWriter */
			XmlWriterSettings xmlSettings = new XmlWriterSettings();
			xmlSettings.Encoding = Encoding.UTF8;
			xmlSettings.Indent = true;
			this.Xml = XmlWriter.Create(this.FileName, xmlSettings);
			
			/*1.3: Writes the initial headers */
			Xml.WriteStartDocument(true);
			Xml.WriteStartElement(_Xml_RootTag);
			base.PreExecute();



			// STEP 2=
			// Gathers information on columns and place it into a ColumnInformation Array
			IDTSInput90 input = ComponentMetaData.InputCollection[0];
			colInfos = new ColumnInformation[input.InputColumnCollection.Count];

			for (int i = 0; i < input.InputColumnCollection.Count; i++)
			{
				ColumnInformation colInfo = new ColumnInformation();
				colInfo.ColumnName = input.InputColumnCollection[i].Name;
				colInfo.BufferIndex = BufferManager.FindColumnByLineageID(input.Buffer, input.InputColumnCollection[i].LineageID);
				colInfo.DataType = input.InputColumnCollection[i].DataType;
				colInfos[i] = colInfo;
			}
		}

		public override void ProcessInput(int inputID, PipelineBuffer buffer)
		{
			int colIt;
			string text;
			string columnName ="";
			int retain = -1;
			Type[] types = new Type[0]; ;

			if (buffer.EndOfRowset == false)
			{
				try
				{
					while (buffer.NextRow())
					{
						this.Xml.WriteStartElement(_Xml_RowTag);

						for (colIt = 0; colIt < colInfos.Length; colIt++)
						{
							if (!buffer.IsNull(colInfos[colIt].BufferIndex))
							{
								text = buffer[colInfos[colIt].BufferIndex].ToString();
								
							
							}
							else
							{
								text = "";
							}
							//text = buffer.GetBytes().ToString();
							columnName = colInfos[colIt].ColumnName;
							this.Xml.WriteElementString(columnName, text);

							retain = colIt;
							//this.Xml.WriteStartElement(colInfos[colIt].ColumnName);
							//this.Xml.WriteEndElement();
						}
						this.Xml.WriteEndElement();
						LineCounter++;
					}
				}
				catch (System.Exception ex)
				{
					bool cancel = false;
					StringBuilder sb = new StringBuilder();
					sb.Append("Caught Exception : ");
					sb.Append(ex.Message);
					sb.Append(" - iteration : ");
					sb.Append(retain);
					sb.Append(" - Nb of columns : ");
					sb.Append(colInfos.Length);

					ComponentMetaData.FireError(0, ComponentMetaData.Name, sb.ToString(), string.Empty, 0, out cancel);
					throw new ApplicationException(Resource.CouldNotProcessInput);
					
				}
			}

		}

		public override void PostExecute()
		{
			if ((bool)this.ComponentMetaData.CustomPropertyCollection[Const_OutputNbOfRows_AttributeName].Value)
			{
				Xml.WriteElementString(_Xml_NbOfRowsTag, Convert.ToString(this.LineCounter));
				Xml.WriteEndElement();
			}			
			Xml.WriteEndDocument();
			Xml.Close();
			base.PostExecute();
		}

	}
}
